/*
 * 这个例程适用于`Linux`这类支持pthread的POSIX设备, 它演示了用SDK配置MQTT参数并建立连接, 之后创建2个线程
 *
 * + 一个线程用于保活长连接
 * + 一个线程用于接收消息, 并在有消息到达时进入默认的数据回调, 在连接状态变化时进入事件回调
 *
 * 接着演示了在MQTT连接上进行属性上报, 事件上报, 以及处理收到的属性设置, 服务调用, 取消这些代码段落的注释即可观察运行效果
 *
 * 需要用户关注或修改的部分, 已经用 TODO 在注释中标明
 *
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

/*增加部分*/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <sys/resource.h>
#include  "cJSON.h"
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
/* */

#include "aiot_state_api.h"
#include "aiot_sysdep_api.h"
#include "aiot_mqtt_api.h"
#include "aiot_dm_api.h"

/*增加部分*/
/*全局变量声明*/
//存储共享内存段的标识符
static int g_shm_id = -1;
//存储消息队列的标识符
static int g_msg_id = -1;
//串口设备文件描述符
//static int g_uart_fd = -1;

/* 传感器数据结构体 */
typedef struct {
    // int temperature;;      // 温度
    // int humidity;     // 湿度
    // int light;     // 光照
    //  int fan;      // 风扇
    // int motor;     // 马达      
    // int buzzer;      // 蜂鸣器
    // int LED1;      // LED1状态
    // int LED2;      // LED2状态
    // int LED3;      // LED3状态
    // int LED4;      // LED4状态
    char status[1024];    // 用于存储JSON字符串
    //int updated;   // 数据更新标志
} SensorData;

/* 消息队列结构体 */
typedef struct {
    long msg_type;          // 消息类型
    size_t data_len;        // 数据长度
    char data[1024];        // 数据缓冲区
} MsgQueue;

#define MSG_TYPE_COMMAND 1  // 命令消息类型

/* 全局变量 */
static SensorData *shared_data = NULL;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/* 命令类型定义 */
#define CMD_OPEN_LED1    1
#define CMD_CLOSE_LED1   0

/* IPC Keys */
#define SHM_KEY 108//共享内存
#define PATHNAME "/home/qwe/1.c"
#define MSG_KEY 102  //消息队列
/**/


/* TODO: 替换为自己设备的三元组 */
const char *product_key       = "k28i9qnUZiO";
const char *device_name       = "device";
const char *device_secret     = "bea57671b22e1021fec8c368d2878aa5";

/*
    TODO: 替换为自己实例的接入点

    对于企业实例, 或者2021年07月30日之后（含当日）开通的物联网平台服务下公共实例
    mqtt_host的格式为"${YourInstanceId}.mqtt.iothub.aliyuncs.com"
    其中${YourInstanceId}: 请替换为您企业/公共实例的Id

    对于2021年07月30日之前（不含当日）开通的物联网平台服务下公共实例，请使用旧版接入点。
    详情请见: https://help.aliyun.com/document_detail/147356.html
*/
const char  *mqtt_host = "iot-06z00ci1pojds5r.mqtt.iothub.aliyuncs.com";
/* 
    原端口：1883/443，对应的证书(GlobalSign R1),于2028年1月过期，届时可能会导致设备不能建连。
    (推荐)新端口：8883，将搭载新证书，由阿里云物联网平台自签证书，于2053年7月过期。
*/
const uint16_t port = 8883;

/* 位于portfiles/aiot_port文件夹下的系统适配函数集合 */
extern aiot_sysdep_portfile_t g_aiot_sysdep_portfile;

/* 位于external/ali_ca_cert.c中的服务器证书 */
extern const char *ali_ca_cert;

/*MQTT客户端相关定义*/
static pthread_t g_mqtt_process_thread;
static pthread_t g_mqtt_recv_thread;
static uint8_t g_mqtt_process_thread_running = 0;
static uint8_t g_mqtt_recv_thread_running = 0;

/* TODO: 如果要关闭日志, 就把这个函数实现为空, 如果要减少日志, 可根据code选择不打印
 *
 * 上面这条日志的code就是0317(十六进制), code值的定义见core/aiot_state_api.h
 *
 */

/* 日志回调函数, SDK的日志会从这里输出 */
int32_t demo_state_logcb(int32_t code, char *message)
{
    printf("%s", message);
    return 0;
}

/* MQTT事件回调函数, 当网络连接/重连/断开时被触发, 事件定义见core/aiot_mqtt_api.h */
void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event, void *userdata)
{
    switch (event->type) {
        /* SDK因为用户调用了aiot_mqtt_connect()接口, 与mqtt服务器建立连接已成功 */
        case AIOT_MQTTEVT_CONNECT: {
            printf("MQTT已连接\n");
        }
        break;

        /* SDK因为网络状况被动断连后, 自动发起重连已成功 */
        case AIOT_MQTTEVT_RECONNECT: {
            printf("MQTT重连成功\n");
        }
        break;

        /* SDK因为网络的状况而被动断开了连接, network是底层读写失败, heartbeat是没有按预期得到服务端心跳应答 */
        case AIOT_MQTTEVT_DISCONNECT: {
            char *cause = (event->data.disconnect == AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) ? ("network disconnect") :
                          ("heartbeat disconnect");
            printf("MQTT连接断开: %s\n", cause);
        }
        break;

        default: {

        }
    }
}

/* 执行aiot_mqtt_process的线程, 包含心跳发送和QoS1消息重发 */
void *demo_mqtt_process_thread(void *args)
{
    int32_t res = STATE_SUCCESS;

    while (g_mqtt_process_thread_running) {
        res = aiot_mqtt_process(args);
        if (res == STATE_USER_INPUT_EXEC_DISABLED) {
            break;
        }
        sleep(1);
    }
    return NULL;
}

/* 执行aiot_mqtt_recv的线程, 包含网络自动重连和从服务器收取MQTT消息 */
void *demo_mqtt_recv_thread(void *args)
{
    int32_t res = STATE_SUCCESS;

    while (g_mqtt_recv_thread_running) {
        res = aiot_mqtt_recv(args);
        if (res < STATE_SUCCESS) {
            if (res == STATE_USER_INPUT_EXEC_DISABLED) {
                break;
            }
            sleep(1);
        }
    }
    return NULL;
}

/* 函数声明 */
static void demo_dm_recv_handler(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_generic_reply(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_property_set(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_async_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_sync_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_raw_data(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_raw_sync_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static void demo_dm_recv_raw_data_reply(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata);
static int32_t demo_send_property_post(void *dm_handle, char *params);

static void demo_dm_recv_generic_reply(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_generic_reply msg_id 消息ID= %d, code 状态码= %d, data 数据= %.*s, message 消息= %.*s\r\n",
           recv->data.generic_reply.msg_id,
           recv->data.generic_reply.code,
           recv->data.generic_reply.data_len,
           recv->data.generic_reply.data,
           recv->data.generic_reply.message_len,
           recv->data.generic_reply.message);
}

//需要在demo_dm_recv_property_set函数中添加对应的指令下达代码

static void demo_dm_recv_property_set(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_property_set msg_id 指令下达消息ID= %ld, params 指令下达字符串= %.*s\r\n",
    (unsigned long)recv->data.property_set.msg_id,
    recv->data.property_set.params_len,
    recv->data.property_set.params);

    /*增加部分*/
     cJSON *root = cJSON_Parse(recv->data.property_set.params);
    if (root) 
    {
        // 创建用于发送的JSON对象
        cJSON *cmd_json = cJSON_CreateObject();
        int has_cmmand = 0;//标记是否有效命令

        //处理LED1
        cJSON *LED1 = cJSON_GetObjectItem(root, "LightSwitch");
        if (LED1) 
        {
            int LED1_value = LED1->valueint;
            printf("收到LED1控制命令,值为: %d\n", LED1_value);
            
            if (LED1_value == 0 || LED1_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "LED1", LED1_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效的LED1状态值: %d\n",LED1_value);
                cJSON_Delete(root);
                return;
            }
        }  
            
        //处理LED2
        cJSON *LED2 = cJSON_GetObjectItem(root, "NightLightSwitch");
        if (LED2) 
        {
            int LED2_value = LED2->valueint;
            printf("收到LED2控制命令,值为: %d\n", LED2_value);
            
            if (LED2_value == 0 || LED2_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "LED2", LED2_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效的LED2状态值: %d\n",LED2_value);
                cJSON_Delete(root);
                return;
            }
        }  

        //处理LED3
        cJSON *LED3 = cJSON_GetObjectItem(root, "RingLEDSwitch");
        if (LED3) 
        {
            int LED3_value = LED3->valueint;
            printf("收到LED3控制命令,值为: %d\n", LED3_value);
            
            if (LED3_value == 0 || LED3_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "LED3", LED3_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效的LED3状态值: %d\n",LED3_value);
                cJSON_Delete(root);
                return;
            }
        }  

        //处理LED4
        cJSON *LED4 = cJSON_GetObjectItem(root, "StatusLightSwitch");
        if (LED4) 
        {
            int LED4_value = LED4->valueint;
            printf("收到LED4控制命令,值为: %d\n", LED4_value);
            
            if (LED4_value == 0 || LED4_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "LED4", LED4_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效的LED4状态值: %d\n",LED4_value);
                cJSON_Delete(root);
                return;
            }
        }  

        //处理fan
        cJSON *fan = cJSON_GetObjectItem(root, "FanSwitch");
        if (fan) 
        {
            int fan_value = fan->valueint;
            printf("收到fan控制命令,值为: %d\n", fan_value);
            
            if (fan_value == 0 || fan_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "fan", fan_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效fan状态值: %d\n",fan_value);
                cJSON_Delete(root);
                return;
            }
        }  
        
        //处理motor
        cJSON *motor = cJSON_GetObjectItem(root, "KitchenVentilator_MotorStall");
        if (motor) 
        {
            int motor_value = motor->valueint;
            printf("收到motor控制命令,值为: %d\n", motor_value);
            
            if (motor_value == 0 || motor_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "motor", motor_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效motor状态值: %d\n",motor_value);
                cJSON_Delete(root);
                return;
            }
        }  

        //处理buzzer
        cJSON *buzzer = cJSON_GetObjectItem(root, "Buzzer");
        if (buzzer) 
        {
            int buzzer_value = buzzer->valueint;
            printf("收到buzzer控制命令,值为: %d\n", buzzer_value);
            
            if (buzzer_value == 0 || buzzer_value == 1)
             {
                cJSON_AddNumberToObject(cmd_json, "buzzer", buzzer_value);
                has_cmmand = 1;
            }
            else
            {
                printf("无效buzzer状态值: %d\n",buzzer_value);
                cJSON_Delete(root);
                return;
            }
        }  

        printf("has_cmmand: %d",has_cmmand);

        if(has_cmmand)
        {
            char *json_str = cJSON_Print(cmd_json);
            printf("\n准备发送的消息详情：\n");
            printf("消息类型: %ld\n", (long)MSG_TYPE_COMMAND);
            printf("数据长度: %zu\n", strlen(json_str));
            printf("消息内容: %s\n", json_str);
            
            // 构建消息队列消息
            MsgQueue msg;
            memset(&msg, 0, sizeof(MsgQueue));
            msg.msg_type = MSG_TYPE_COMMAND;
            msg.data_len = strlen(json_str);
            strncpy(msg.data, json_str, sizeof(msg.data) - 1);

            // 打印实际发送的消息内容
            printf("消息队列ID: %d\n", g_msg_id);
            printf("最终发送的消息内容: %s\n", msg.data);
            
            // 发送消息到STM32
            if(msgsnd(g_msg_id, &msg, sizeof(MsgQueue) - sizeof(long), IPC_NOWAIT) == -1) 
            {
                printf("发送消息到STM32失败: %s\n", strerror(errno));
                printf("发送消息失败，错误码：%d\n", errno);

                // 检查消息队列状态
                struct msqid_ds queue_stat;
                if(msgctl(g_msg_id, IPC_STAT, &queue_stat) != -1)
                {
                printf("消息队列当前消息数：%lu\n", queue_stat.msg_qnum);
                printf("消息队列最大字节数：%lu\n", queue_stat.msg_qbytes);
                }
            }
             else 
             {
                printf("发送控制命令成功\n");
            }
            free(json_str);
        }   
        cJSON_Delete(cmd_json);
        cJSON_Delete(root);
    }    
    /**/



    /* TODO: 以下代码演示如何对来自云平台的属性设置指令进行应答, 用户可取消注释查看演示效果 */
    
    //回复云平台
    aiot_dm_msg_t msg;
    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_PROPERTY_SET_REPLY;
    msg.data.property_set_reply.msg_id = recv->data.property_set.msg_id;
    msg.data.property_set_reply.code = 200;
    msg.data.property_set_reply.data = "{}";
    int32_t res = aiot_dm_send(dm_handle, &msg);
    if (res < 0)
    {
        printf("aiot_dm_send failed\r\n");
    }
}

static void demo_dm_recv_async_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_async_service_invoke msg_id = %ld, service_id = %s, params = %.*s\r\n",
           (unsigned long)recv->data.async_service_invoke.msg_id,
           recv->data.async_service_invoke.service_id,
           recv->data.async_service_invoke.params_len,
           recv->data.async_service_invoke.params);

    /* TODO: 以下代码演示如何对来自云平台的异步服务调用进行应答, 用户可取消注释查看演示效果
        *
        * 注意: 如果用户在回调函数外进行应答, 需要自行保存msg_id, 因为回调函数入参在退出回调函数后将被SDK销毁, 不可以再访问到
        */

   
    {
        aiot_dm_msg_t msg;

        memset(&msg, 0, sizeof(aiot_dm_msg_t));
        msg.type = AIOT_DMMSG_ASYNC_SERVICE_REPLY;
        msg.data.async_service_reply.msg_id = recv->data.async_service_invoke.msg_id;
        msg.data.async_service_reply.code = 200;
        msg.data.async_service_reply.service_id = "ToggleLightSwitch";
        msg.data.async_service_reply.data = "{\"dataA\": 20}";
        int32_t res = aiot_dm_send(dm_handle, &msg);
        if (res < 0) {
            printf("aiot_dm_send failed\r\n");
        }
    }
    
}

static void demo_dm_recv_sync_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_sync_service_invoke msg_id = %ld, rrpc_id = %s, service_id = %s, params = %.*s\r\n",
           (unsigned long)recv->data.sync_service_invoke.msg_id,
           recv->data.sync_service_invoke.rrpc_id,
           recv->data.sync_service_invoke.service_id,
           recv->data.sync_service_invoke.params_len,
           recv->data.sync_service_invoke.params);

    /* TODO: 以下代码演示如何对来自云平台的同步服务调用进行应答, 用户可取消注释查看演示效果
        *
        * 注意: 如果用户在回调函数外进行应答, 需要自行保存msg_id和rrpc_id字符串, 因为回调函数入参在退出回调函数后将被SDK销毁, 不可以再访问到
        */

    
    {
        aiot_dm_msg_t msg;

        memset(&msg, 0, sizeof(aiot_dm_msg_t));
        msg.type = AIOT_DMMSG_SYNC_SERVICE_REPLY;
        msg.data.sync_service_reply.rrpc_id = recv->data.sync_service_invoke.rrpc_id;
        msg.data.sync_service_reply.msg_id = recv->data.sync_service_invoke.msg_id;
        msg.data.sync_service_reply.code = 200;
        msg.data.sync_service_reply.service_id = "SetLightSwitchTimer";
        msg.data.sync_service_reply.data = "{}";
        int32_t res = aiot_dm_send(dm_handle, &msg);
        if (res < 0) {
            printf("aiot_dm_send failed\r\n");
        }
    }
}

static void demo_dm_recv_raw_data(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_raw_data raw data len = %d\r\n", recv->data.raw_data.data_len);
    /* TODO: 以下代码演示如何发送二进制格式数据, 若使用需要有相应的数据透传脚本部署在云端 */
   
    {
        aiot_dm_msg_t msg;
        uint8_t raw_data[] = {0x01, 0x02};

        memset(&msg, 0, sizeof(aiot_dm_msg_t));
        msg.type = AIOT_DMMSG_RAW_DATA;
        msg.data.raw_data.data = raw_data;
        msg.data.raw_data.data_len = sizeof(raw_data);
        aiot_dm_send(dm_handle, &msg);
    }
    
}

static void demo_dm_recv_raw_sync_service_invoke(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_raw_sync_service_invoke raw sync service rrpc_id = %s, data_len = %d\r\n",
           recv->data.raw_service_invoke.rrpc_id,
           recv->data.raw_service_invoke.data_len);
}

static void demo_dm_recv_raw_data_reply(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_raw_data_reply receive reply for up_raw msg, data len = %d\r\n", recv->data.raw_data.data_len);
    /* TODO: 用户处理下行的二进制数据, 位于recv->data.raw_data.data中 */
}

/* 用户数据接收处理回调函数 */
static void demo_dm_recv_handler(void *dm_handle, const aiot_dm_recv_t *recv, void *userdata)
{
    printf("demo_dm_recv_handler, type = %d\r\n", recv->type);

    switch (recv->type) {

        /* 属性上报, 事件上报, 获取期望属性值或者删除期望属性值的应答 */
        case AIOT_DMRECV_GENERIC_REPLY: {
            demo_dm_recv_generic_reply(dm_handle, recv, userdata);
        }
        break;

        /* 属性设置 */
        case AIOT_DMRECV_PROPERTY_SET: {
            demo_dm_recv_property_set(dm_handle, recv, userdata);
        }
        break;

        /* 异步服务调用 */
        case AIOT_DMRECV_ASYNC_SERVICE_INVOKE: {
            demo_dm_recv_async_service_invoke(dm_handle, recv, userdata);
        }
        break;

        /* 同步服务调用 */
        case AIOT_DMRECV_SYNC_SERVICE_INVOKE: {
            demo_dm_recv_sync_service_invoke(dm_handle, recv, userdata);
        }
        break;

        /* 下行二进制数据 */
        case AIOT_DMRECV_RAW_DATA: {
            demo_dm_recv_raw_data(dm_handle, recv, userdata);
        }
        break;

        /* 二进制格式的同步服务调用, 比单纯的二进制数据消息多了个rrpc_id */
        case AIOT_DMRECV_RAW_SYNC_SERVICE_INVOKE: {
            demo_dm_recv_raw_sync_service_invoke(dm_handle, recv, userdata);
        }
        break;

        /* 上行二进制数据后, 云端的回复报文 */
        case AIOT_DMRECV_RAW_DATA_REPLY: {
            demo_dm_recv_raw_data_reply(dm_handle, recv, userdata);
        }
        break;

        default:
            break;
    }
}

/* 属性上报函数演示 */
int32_t demo_send_property_post(void *dm_handle, char *params)
{
    aiot_dm_msg_t msg;

    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_PROPERTY_POST;
    msg.data.property_post.params = params;

    return aiot_dm_send(dm_handle, &msg);
}

int32_t demo_send_property_batch_post(void *dm_handle, char *params)
{
    aiot_dm_msg_t msg;

    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_PROPERTY_BATCH_POST;
    msg.data.property_post.params = params;

    return aiot_dm_send(dm_handle, &msg);
}

/* 事件上报函数演示 */
int32_t demo_send_event_post(void *dm_handle, char *event_id, char *params)
{
    aiot_dm_msg_t msg;

    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_EVENT_POST;
    msg.data.event_post.event_id = event_id;
    msg.data.event_post.params = params;

    return aiot_dm_send(dm_handle, &msg);
}

/* 演示了获取属性LightSwitch的期望值, 用户可将此函数加入到main函数中运行演示 */
int32_t demo_send_get_desred_requset(void *dm_handle)
{
    aiot_dm_msg_t msg;

    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_GET_DESIRED;
    msg.data.get_desired.params = "[\"LightSwitch\"]";

    return aiot_dm_send(dm_handle, &msg);
}

/* 演示了删除属性LightSwitch的期望值, 用户可将此函数加入到main函数中运行演示 */
int32_t demo_send_delete_desred_requset(void *dm_handle)
{
    aiot_dm_msg_t msg;

    memset(&msg, 0, sizeof(aiot_dm_msg_t));
    msg.type = AIOT_DMMSG_DELETE_DESIRED;
    msg.data.get_desired.params = "{\"LightSwitch\":{}}";

    return aiot_dm_send(dm_handle, &msg);
}

 /*增加部分*/
static int init_ipc(void)
{
     // 计算需要的共享内存大小
    size_t shm_size = sizeof(SensorData);
    printf("尝试创建共享内存，大小: %zu bytes\n", shm_size);

    key_t key = ftok(PATHNAME,SHM_KEY);
    if(key == -1)
    {
        perror("ftok");
        return -1;
    }

    //创建或获取共享内存
    g_shm_id = shmget(key, shm_size, IPC_CREAT | 0666);
    if(g_shm_id == -1)
    {
        printf("创建共享内存失败：%s(erron=%d)\n", strerror(errno),errno);
        g_shm_id = shmget(key, 0, 0);
        if(g_shm_id != -1) 
        {
            printf("共享内存段已存在，尝试删除...\n");
            if(shmctl(g_shm_id, IPC_RMID, NULL) == -1) 
            {
                printf("删除已存在的共享内存段失败: %s\n", strerror(errno));
                return -1;
            }
            // 重新创建
            g_shm_id = shmget(key, shm_size, IPC_CREAT | 0666);
            if(g_shm_id == -1) 
            {
                printf("重新创建共享内存失败：%s\n", strerror(errno));
                return -1;
            }
        }
        else
        {
        return -1;
        }
    }

    // 映射共享内存
    shared_data = (SensorData *)shmat(g_shm_id, NULL, 0);
    if(shared_data == (void *)-1)
    {
        printf("映射共享内存失败：%s\n", strerror(errno));
        return -1;
    }

    // 初始化共享内存数据
    memset(shared_data, 0, sizeof(SensorData));

    key_t key1 = ftok(PATHNAME,MSG_KEY);
    if(key1 == -1)
    {
        perror("ftok");
        return -1;
    }

    //创建或获取消息队列
    g_msg_id = msgget(key1, IPC_CREAT | 0666);
    if(g_msg_id == -1)
    {
        printf("创建消息队列失败：%s\n", strerror(errno));
        return -1;
    }
    printf("IPC初始化成功,共享内存ID: %d, 消息队列ID: %d\n", g_shm_id, g_msg_id);
    return 0;
}

//清理函数
static void cleanup_ipc(void)
{
    if(shared_data) 
    {
        if(shmdt(shared_data) == -1) 
        {
            printf("断开共享内存连接失败: %s\n", strerror(errno));
        }
        shared_data = NULL;
    }

    // 删除共享内存段
    if(g_shm_id != -1)
    {
        if(shmctl(g_shm_id, IPC_RMID, NULL) == -1)
        {
            printf("删除共享内存段失败: %s\n", strerror(errno));
        }
    }

    // 删除消息队列
    if(g_msg_id != -1)
    {
        if(msgctl(g_msg_id, IPC_RMID, NULL) == -1)
        {
            printf("删除消息队列失败: %s\n", strerror(errno));
        }
    }
}
/**/

int main(int argc, char *argv[])
{
    /*增加部分*/
    struct rlimit rlim;
    if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
        if (rlim.rlim_cur < 1024) {
            printf("警告: 当前文件描述符限制较低: %ld\n", 
                   (long)rlim.rlim_cur);
        }
    }
    /**/

    int32_t     res = STATE_SUCCESS;
    void       *dm_handle = NULL;
    void       *mqtt_handle = NULL;
    aiot_sysdep_network_cred_t cred; /* 安全凭据结构体, 如果要用TLS, 这个结构体中配置CA证书等参数 */
    uint8_t post_reply = 1;


    /* 配置SDK的底层依赖 */
    aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
    /* 配置SDK的日志输出 */
    aiot_state_set_logcb(demo_state_logcb);

    /* 创建SDK的安全凭据, 用于建立TLS连接 */
    memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
    cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA;  /* 使用RSA证书校验MQTT服务端 */
    cred.max_tls_fragment = 16384; /* 最大的分片长度为16K, 其它可选值还有4K, 2K, 1K, 0.5K */
    cred.sni_enabled = 1;                               /* TLS建连时, 支持Server Name Indicator */
    cred.x509_server_cert = ali_ca_cert;                 /* 用来验证MQTT服务端的RSA根证书 */
    cred.x509_server_cert_len = strlen(ali_ca_cert);     /* 用来验证MQTT服务端的RSA根证书长度 */

    /* 创建1个MQTT客户端实例并内部初始化默认参数 */
    mqtt_handle = aiot_mqtt_init();
    if (mqtt_handle == NULL) {
        printf("aiot_mqtt_init failed\n");
        return -1;
    }

    /* 配置MQTT服务器地址 */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)mqtt_host);
    /* 配置MQTT服务器端口 */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port);
    /* 配置设备productKey */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key);
    /* 配置设备deviceName */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name);
    /* 配置设备deviceSecret */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret);
    /* 配置网络连接的安全凭据, 上面已经创建好了 */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred);
    /* 配置MQTT事件回调函数 */
    aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler);

    /* 创建DATA-MODEL实例 */
    dm_handle = aiot_dm_init();
    if (dm_handle == NULL) {
        printf("aiot_dm_init failed");
        return -1;
    }
    /* 配置MQTT实例句柄 */
    aiot_dm_setopt(dm_handle, AIOT_DMOPT_MQTT_HANDLE, mqtt_handle);
    /* 配置消息接收处理回调函数 */
    aiot_dm_setopt(dm_handle, AIOT_DMOPT_RECV_HANDLER, (void *)demo_dm_recv_handler);

    /* 配置是云端否需要回复post_reply给设备. 如果为1, 表示需要云端回复, 否则表示不回复 */
    aiot_dm_setopt(dm_handle, AIOT_DMOPT_POST_REPLY, (void *)&post_reply);

    /* 与服务器建立MQTT连接 */
    res = aiot_mqtt_connect(mqtt_handle);
    if (res < STATE_SUCCESS) {
        /* 尝试建立连接失败, 销毁MQTT实例, 回收资源 */
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        printf("aiot_mqtt_connect failed: -0x%04X\n\r\n", -res);
        printf("please check variables like mqtt_host, produt_key, device_name, device_secret in demo\r\n");
        return -1;
    }

    /*增加部分*/
    /* 初始化IPC */
    if(init_ipc() != 0) {
        printf("IPC 初始化失败\n");
        printf("请检查是否有创建 IPC 资源的权限\n");
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        return -1;
    }
    /**/

    /* 向服务器订阅property/batch/post_reply这个topic */
    aiot_mqtt_sub(mqtt_handle, "/sys/k28i9qnUZiO/device/thing/event/property/batch/post_reply", NULL, 1,
                  NULL);

    /* 创建一个单独的线程, 专用于执行aiot_mqtt_process, 它会自动发送心跳保活, 以及重发QoS1的未应答报文 */
    g_mqtt_process_thread_running = 1;
    res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle);
    if (res < 0) {
        printf("pthread_create demo_mqtt_process_thread failed: %d\n", res);
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        return -1;
    }

    /* 创建一个单独的线程用于执行aiot_mqtt_recv, 它会循环收取服务器下发的MQTT消息, 并在断线时自动重连 */
    g_mqtt_recv_thread_running = 1;
    res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle);
    if (res < 0) {
        printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res);
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        return -1;
    }

    /* 主循环进入休眠 */
    while (1) 
    {
        /*增加部分*/
        if(shared_data != NULL)
        {
            pthread_mutex_lock(&mutex);
            char *json_data = shared_data->status;  // 获取共享内存中的JSON字符串
            //int updated = shared_data->updated;
            pthread_mutex_unlock(&mutex);

            if(1)
            {
                printf("收到JSON数据: %s\n", json_data);
            
                // 解析JSON数据
                cJSON *root = cJSON_Parse(json_data);
                if(root)
                {
                    // 解析温湿度和LED状态
                    double temperature = 0;
                    double humidity = 0;
                    int led1_status = 0;
                    int led2_status = 0;
                    int led3_status = 0;
                    int led4_status = 0;
                    int light = 0;
                    int fan_status = 0;
                    int motor_status = 0;
                    int buzzer_status = 0;
                    int has_data = 0;//是否成功解析到数据

                    //解析风扇
                    cJSON *fan_status_json = cJSON_GetObjectItem(root, "fan");
                    if (fan_status_json)
                    {
                        fan_status=fan_status_json->valueint;
                        has_data = 1;
                        printf("解析到风扇状态:%d\n",fan_status);
                    }

                    //解析马达
                    cJSON *motor_status_json = cJSON_GetObjectItem(root, "motor");
                    if(motor_status_json)
                    {
                        motor_status=motor_status_json->valueint;
                        has_data = 1;
                        printf("解析到马达状态:%d\n",motor_status);

                    }

                    //解析蜂鸣器
                    cJSON *buzzer_status_json = cJSON_GetObjectItem(root, "buzzer");
                    if(buzzer_status_json)
                    {
                        buzzer_status=buzzer_status_json->valueint;
                        has_data = 1;
                        printf("解析到蜂鸣器状态:%d\n",buzzer_status);

                    }

                    //解析环境光
                    cJSON *light_data_json = cJSON_GetObjectItem(root, "light");
                    if(light_data_json)
                    {
                        light = light_data_json->valueint;
                        has_data = 1;
                        printf("解析到环境光数据: %d\n",light);
                    }

                    // 解析温度
                    cJSON *temp_data_json = cJSON_GetObjectItem(root, "temperature");
                    if(temp_data_json)
                    {
                        temperature = temp_data_json->valueint;
                        has_data = 1;
                        printf("解析到温度: %.2lf\n", temperature);
                    }

                    // 解析湿度
                    cJSON *humi_data_json = cJSON_GetObjectItem(root, "humidity");
                    if(humi_data_json)
                    {
                        humidity = humi_data_json->valueint;
                        has_data = 1;
                        printf("解析到湿度: %.2lf\n", humidity);
                    }

                    // 解析LED状态
                    cJSON *led1_status_json = cJSON_GetObjectItem(root, "LED1");
                    if(led1_status_json)
                    {
                        led1_status = led1_status_json->valueint;
                        has_data = 1;
                        printf("解析到LED1状态: %d\n", led1_status);
                    }

                    cJSON *led2_status_json = cJSON_GetObjectItem(root, "LED2");
                    if(led2_status_json)
                    {
                        led2_status = led2_status_json->valueint;
                        has_data = 1;
                        printf("解析到LED2状态: %d\n", led2_status);
                    }

                    cJSON *led3_status_json = cJSON_GetObjectItem(root, "LED3");
                    if(led3_status_json)
                    {
                        led3_status = led3_status_json->valueint;
                        has_data = 1;
                        printf("解析到LED3状态: %d\n", led3_status);
                    }

                    cJSON *led4_status_json = cJSON_GetObjectItem(root, "LED4");
                    if(led4_status_json)
                    {
                        led4_status = led4_status_json->valueint;
                        has_data = 1;
                        printf("解析到LED4状态: %d\n", led4_status);
                    }

                    // 如果解析到数据，构建上报字符串
                    if(has_data)
                    {
                        char property_payload[256];
                        snprintf(property_payload, sizeof(property_payload), 
                                "{\"temperature\":%.2lf, \"Humidity\":%.2lf, \"LightSwitch\":%d,\"NightLightSwitch\":%d,\"RingLEDSwitch\":%d,\"StatusLightSwitch\":%d,\"FanSwitch\":%d,\"KitchenVentilator_MotorStall\":%d,\"LightLux\":%d,\"Buzzer\":%d}", 
                                temperature, humidity,led1_status, led2_status, led3_status, led4_status,fan_status, motor_status, light, buzzer_status);

                        //在发送前并检查结果
                        printf("\n准备上报数据到阿里云:\n");
                        printf("温度: %.2lf\n", temperature);
                        printf("湿度: %.2lf\n", humidity);
                        printf("LED状态: %d %d %d %d\n", led1_status, led2_status, led3_status, led4_status);
                        printf("其他设备状态: 风扇=%d 电机=%d 光照=%d 蜂鸣器=%d\n", fan_status, motor_status, light, buzzer_status);
                        printf("完整JSON: %s\n\n", property_payload);
                        

                        // 上报到云平台
                        int32_t res = demo_send_property_post(dm_handle, property_payload);
                        if(res < 0)
                        {
                            printf("状态上报失败: -0x%04X\n", -res);
                            switch(res)
                            {
                                case -0x0101:
                                    printf("错误: 参数无效\n");
                                    break;
                                case -0x0102:
                                    printf("错误: 内存分配失败\n");
                                    break;
                                case -0x0103:
                                    printf("错误: 数据发送失败\n");
                                    break;
                                default:
                                    printf("错误: 未知错误码\n");
                            }
                        }
                        else 
                        {
                            printf("状态上报成功\n");
                            
                        }
                    }
                    // 清理JSON对象
                    cJSON_Delete(root);
                }
                else
                {
                    printf("JSON解析失败\n");
                }

            }
            //usleep(100000);  // 100ms检查一次
            sleep(1);//1s检查一次
        }
    
        /* TODO: 以下代码演示了简单的属性上报和事件上报, 用户可取消注释观察演示效果 */
        // demo_send_property_post(dm_handle, "{\"LightSwitch\": 2}");
        // demo_send_property_post(dm_handle, "{\"LightCurrent\": 1.5}");
        
        /*
        demo_send_event_post(dm_handle, "Error", "{\"ErrorCode\": 0}");
        */

        /* TODO: 以下代码演示了基于模块的物模型的上报, 用户可取消注释观察演示效果
         * 本例需要用户在产品的功能定义的页面中, 点击"编辑草稿", 增加一个名为demo_extra_block的模块,
         * 再到该模块中, 通过添加标准功能, 选择一个名为NightLightSwitch的物模型属性, 再点击"发布上线".
         * 有关模块化的物模型的概念, 请见 https://help.aliyun.com/document_detail/73727.html
        */
       /*
        demo_send_property_post(dm_handle, "{\"demo_extra_block:	NightLightSwitch\": 1}");
       */

        /* TODO: 以下代码显示批量上报用户数据, 用户可取消注释观察演示效果
         * 具体数据格式请见https://help.aliyun.com/document_detail/89301.html 的"设备批量上报属性、事件"一节
        */
       
        //char* json = "{\"LightSwitch\": 20, \"LightCurrent\": 8}";

        // 调用函数发送合并后的属性
        //demo_send_property_post(dm_handle, json);

        // demo_send_property_batch_post(dm_handle,
        //                               "{\"LightSwitch\":1,\"LightCurrent\":5}");
       

        //sleep(5);
    }
    /* 在程序退出前清理IPC资源 */
    cleanup_ipc();
    /**/


    /* 停止收发动作 */
    g_mqtt_process_thread_running = 0;
    g_mqtt_recv_thread_running = 0;

    /* 断开MQTT连接, 一般不会运行到这里 */
    res = aiot_mqtt_disconnect(mqtt_handle);
    if (res < STATE_SUCCESS)
    {
        aiot_dm_deinit(&dm_handle);
        aiot_mqtt_deinit(&mqtt_handle);
        printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
        return -1;
    }

    /* 销毁DATA-MODEL实例, 一般不会运行到这里 */
    res = aiot_dm_deinit(&dm_handle);
    if (res < STATE_SUCCESS)
    {
        printf("aiot_dm_deinit failed: -0x%04X\n", -res);
        return -1;
    }

    /* 销毁MQTT实例, 一般不会运行到这里 */
    res = aiot_mqtt_deinit(&mqtt_handle);
    if (res < STATE_SUCCESS)
    {
        printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
        return -1;
    }

    pthread_join(g_mqtt_process_thread, NULL);
    pthread_join(g_mqtt_recv_thread, NULL);

    return 0;
}

